import { DeviceEventEmitter } from "react-native";
import { Observable } from "rxjs";
import { publish, refCount } from "rxjs/operators";
import * as RNSensors from "./rnsensors";

const listenerKeys = new Map([
  ["accelerometer", "Accelerometer"],
  ["gyroscope", "Gyroscope"],
  ["magnetometer", "Magnetometer"],
  ["barometer", "Barometer"],
  ["orientation", "Orientation"],
  ["gravity", "gravityClick"],
]);

const eventEmitterSubscription = new Map([
  ["accelerometer", null],
  ["gyroscope", null],
  ["magnetometer", null],
  ["barometer", null],
  ["orientation", null],
  ["gravity", null],
]);

function createSensorObservable(sensorType) {
  return Observable.create(function subscribe(observer) {
    this.isSensorAvailable = false;
    this.unsubscribeCallback = () => {
      if (!this.isSensorAvailable) return;
      if (eventEmitterSubscription.get(sensorType))
        eventEmitterSubscription.get(sensorType).remove();
      RNSensors.stop(sensorType);
      RNSensors.setUpdateInterval(sensorType, 0);
      RNSensors.setLogLevelForType(sensorType, 0);
    };
    RNSensors.isAvailable(sensorType).then((res) => {
      this.isSensorAvailable = true;
      if (!res) {
        observer.error(`Sensors${sensorType} is not available`);
        return;
      } else {
        RNSensors.start(sensorType);
        eventEmitterSubscription.set(
          sensorType,
          DeviceEventEmitter.addListener(
            listenerKeys.get(sensorType),
            (date) => {
              observer.next(date);
            }
          )
        );
      }
    });
    return this.unsubscribeCallback;
  }).pipe(makeSingleton());
}

// As we only have one sensor we need to share it between the different consumers
function makeSingleton() {
  return (source) => source.pipe(publish(), refCount());
}

const accelerometer = createSensorObservable("accelerometer");
const gyroscope = createSensorObservable("gyroscope");
const magnetometer = createSensorObservable("magnetometer");
const barometer = createSensorObservable("barometer");
const orientation = createSensorObservable("orientation");
const gravity = createSensorObservable("gravity");

export default {
  gyroscope,
  accelerometer,
  magnetometer,
  barometer,
  orientation,
  gravity,
};